package com.ruoyi.security.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.security.domain.SecurityDayMinuteTrade;
import com.ruoyi.security.mapper.SecurityDayMinuteTradeMapper;
import com.ruoyi.security.service.ISecurityTimeShareService;
import com.ruoyi.security.vo.SecurityTimeShareVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yeoman
 * @date 2025/1/15 15:30
 * @description 证券分时图服务实现类
 */
@Slf4j
@Service
public class SecurityTimeShareServiceImpl implements ISecurityTimeShareService {

    @Resource
    private SecurityDayMinuteTradeMapper securityDayMinuteTradeMapper;

    @Override
    public SecurityTimeShareVo getTimeShareData(String symbol, String startDate, String endDate) {
        log.info("获取证券分时数据，证券代码：{}，开始日期：{}，结束日期：{}", symbol, startDate, endDate);
        
        SecurityTimeShareVo result = new SecurityTimeShareVo();
        
        // 1. 获取分时交易数据
        List<SecurityDayMinuteTrade> tradeList = getSecurityDayMinuteTradeList(symbol, startDate, endDate);
        
        // 2. 从分时交易数据中获取证券基本信息
        SecurityTimeShareVo.SecurityInfo securityInfo = getSecurityInfo(symbol, tradeList);
        
        // 3. 计算昨收价、今开价、最高价、最低价
        calculatePriceInfo(securityInfo, tradeList);
        
        result.setSecurityInfo(securityInfo);
        
        // 4. 处理分时价格数据
        List<List<String>> timeshareData = processTimeshareData(tradeList);
        result.setTimeshareData(timeshareData);

        // 5. 处理分时涨跌幅数据
        List<List<String>> changePercentData = processChangePercentData(tradeList);
        result.setChangePercentData(changePercentData);
        
        // 6. 处理价格均线数据
        List<List<String>> averagePriceData = processAveragePriceData(tradeList);
        result.setAveragePriceData(averagePriceData);
        
        // 7. 处理成交量数据
        List<List<Object>> volumeData = processVolumeData(tradeList);
        result.setVolumeData(volumeData);
        
        return result;
    }


    /**
     * 从分时交易数据中获取证券基本信息
     */
    private SecurityTimeShareVo.SecurityInfo getSecurityInfo(String symbol, List<SecurityDayMinuteTrade> tradeList) {
        SecurityTimeShareVo.SecurityInfo securityInfo = new SecurityTimeShareVo.SecurityInfo();
        
        if (tradeList != null && !tradeList.isEmpty()) {
            // 从第一条记录获取证券信息
            SecurityDayMinuteTrade firstTrade = tradeList.get(0);
            securityInfo.setSymbol(firstTrade.getSymbol());
            securityInfo.setCode(firstTrade.getCode());
            securityInfo.setName(firstTrade.getName() != null ? firstTrade.getName() : "未知证券");
            securityInfo.setDate(firstTrade.getDate());
            securityInfo.setWeekday(firstTrade.getWeekday());
        } else {
            // 如果没有交易数据，设置默认值
            securityInfo.setSymbol(symbol);
            String code = symbol.replaceAll("^(sh|sz|bj)", "");
            securityInfo.setCode(code);
        }
        
        return securityInfo;
    }

    /**
     * 计算价格信息（昨收价、今开价、最高价、最低价）
     */
    private void calculatePriceInfo(SecurityTimeShareVo.SecurityInfo securityInfo, List<SecurityDayMinuteTrade> tradeList) {
        if (tradeList == null || tradeList.isEmpty()) {
            return;
        }

        // 按日期分组
        Map<Date, List<SecurityDayMinuteTrade>> tradesByDate = tradeList.stream()
                .collect(Collectors.groupingBy(SecurityDayMinuteTrade::getDate));

        // 获取所有日期并排序
        List<Date> sortedDates = tradesByDate.keySet().stream()
                .sorted(Date::compareTo)
                .collect(Collectors.toList());

        if (sortedDates.isEmpty()) {
            return;
        }

        // 获取最新日期（当前交易日）
        Date currentDate = sortedDates.get(sortedDates.size() - 1);
        
        // 计算今开价、最高价、最低价：从当前交易日的数据中获取
        List<SecurityDayMinuteTrade> currentDateTrades = tradesByDate.get(currentDate);
        
        // 今开价：9:30分的价格
        BigDecimal openPrice = currentDateTrades.stream()
                .filter(trade -> "09:30".equals(trade.getTime()))
                .map(SecurityDayMinuteTrade::getPrice)
                .findFirst()
                .orElse(new BigDecimal("0"));
        securityInfo.setOpenPrice(openPrice);
        
        // 计算昨收价：9:30分价格减去涨跌幅度
        BigDecimal previousClosePrice = new BigDecimal("0");
        if (!"0".equals(openPrice)) {
            // 获取9:30分的涨跌幅度
            BigDecimal riseFallRange = currentDateTrades.stream()
                    .filter(trade -> "09:30".equals(trade.getTime()))
                    .map(SecurityDayMinuteTrade::getRiseFallRange)
                    .findFirst()
                    .orElse(new BigDecimal("0"));
            
            try {
                // 昨收价 = 今开价 - 涨跌幅度
                BigDecimal previousClosePriceDecimal = openPrice.subtract(riseFallRange);
                previousClosePrice = previousClosePriceDecimal;
            } catch (NumberFormatException e) {
                log.warn("价格计算失败，使用默认值: {}", e.getMessage());
                previousClosePrice = openPrice; // 如果计算失败，使用今开价作为昨收价
            }
        }
        securityInfo.setPreviousClosePrice(previousClosePrice);

        // 最高价：当前交易日所有记录中的最高价格
        BigDecimal highestPrice = currentDateTrades.stream()
                .map(SecurityDayMinuteTrade::getPrice)
                .filter(StringUtils::isNotNull)
                .max(BigDecimal::compareTo)
                .orElse(new BigDecimal("0"));
        securityInfo.setHighestPrice(highestPrice);

        // 最低价：当前交易日所有记录中的最低价格
        BigDecimal lowestPrice = currentDateTrades.stream()
                .map(SecurityDayMinuteTrade::getPrice)
                .filter(StringUtils::isNotNull)
                .min(BigDecimal::compareTo)
                .orElse(new BigDecimal("0"));
        securityInfo.setLowestPrice(lowestPrice);
        
        // 从数据库查询中获取最大涨跌幅（按涨跌幅排序）
        BigDecimal maxRisePercent = currentDateTrades.stream()
                .map(SecurityDayMinuteTrade::getRiseFallRange)
                .filter(StringUtils::isNotNull)
                .max(BigDecimal::compareTo)
                .orElse(new BigDecimal("0"));
        securityInfo.setMaxRisePercent(maxRisePercent);

        BigDecimal maxFallPercent = currentDateTrades.stream()
                .map(SecurityDayMinuteTrade::getRiseFallRange)
                .filter(StringUtils::isNotNull)
                .min(BigDecimal::compareTo)
                .orElse(new BigDecimal("0"));
        securityInfo.setMaxFallPercent(maxFallPercent);
        
    }

    /**
     * 获取分时交易数据列表（按开始和结束日期范围）
     */
    private List<SecurityDayMinuteTrade> getSecurityDayMinuteTradeList(String symbol, String startDate, String endDate) {
        try {
            // 解析开始和结束日期
            Date start = DateUtils.dateTime(DateUtils.YYYY_MM_DD, startDate);
            Date end = DateUtils.dateTime(DateUtils.YYYY_MM_DD, endDate);
            
            // 查询指定日期范围内的分时交易数据
            LambdaQueryWrapper<SecurityDayMinuteTrade> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SecurityDayMinuteTrade::getSymbol, symbol)
                       .ge(SecurityDayMinuteTrade::getDate, start)
                       .le(SecurityDayMinuteTrade::getDate, end);
            
            // 按日期和时间排序
            queryWrapper.orderByAsc(SecurityDayMinuteTrade::getDate)
                       .orderByAsc(SecurityDayMinuteTrade::getTime);
            
            List<SecurityDayMinuteTrade> allTradeList = securityDayMinuteTradeMapper.selectList(queryWrapper);
            
            log.info("查询到{}条分时交易数据，证券代码：{}，日期范围：{} - {}", 
                allTradeList.size(), symbol, startDate, endDate);
            
            return allTradeList;
                    
        } catch (Exception e) {
            log.error("获取分时交易数据失败，证券代码：{}，开始日期：{}，结束日期：{}", 
                symbol, startDate, endDate, e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 处理分时价格数据
     */
    private List<List<String>> processTimeshareData(List<SecurityDayMinuteTrade> tradeList) {
        return tradeList.stream()
                .map(trade -> Arrays.asList(trade.getTime(), trade.getPrice().toString()))
                .collect(Collectors.toList());
    }

    /**
     * 处理分时涨跌幅数据
     */
    private List<List<String>> processChangePercentData(List<SecurityDayMinuteTrade> tradeList) {
        return tradeList.stream()
                .map(trade -> {
                    // 直接使用数据库中的涨跌百分比字段
                    BigDecimal riseFallPercentage = trade.getRiseFallPercentage();
                    if (riseFallPercentage == null) {
                        return Arrays.asList(trade.getTime(), "0.00");
                    }
                    return Arrays.asList(trade.getTime(), riseFallPercentage.toString());
                })
                .collect(Collectors.toList());
    }

    /**
     * 处理价格均线数据
     */
    private List<List<String>> processAveragePriceData(List<SecurityDayMinuteTrade> tradeList) {
        return tradeList.stream()
                .map(trade -> {
                    // 直接使用数据库中的均价字段
                    BigDecimal averagePrice = trade.getAveragePrice();
                    if (averagePrice == null) {
                        // 如果没有均价数据，使用价格作为替代
                        return Arrays.asList(trade.getTime(), trade.getPrice().toString());
                    }
                    return Arrays.asList(trade.getTime(), averagePrice.toString());
                })
                .collect(Collectors.toList());
    }

    /**
     * 处理成交量数据
     */
    private List<List<Object>> processVolumeData(List<SecurityDayMinuteTrade> tradeList) {
        return tradeList.stream()
                .map(trade -> {
                    // 将成交量转换为数字
                    Object volume = parseVolume(trade.getVolume().toString());
                    return Arrays.asList(trade.getTime(), volume);
                })
                .collect(Collectors.toList());
    }



    /**
     * 解析成交量字符串为数字
     */
    private Object parseVolume(String volumeStr) {
        if (StringUtils.isBlank(volumeStr)) {
            return 0;
        }
        
        try {
            // 移除单位（如"万手"、"手"等）
            String cleanVolume = volumeStr.replaceAll("[万千百手]", "");
            return new BigDecimal(cleanVolume).longValue();
        } catch (Exception e) {
            log.warn("解析成交量失败：{}", volumeStr, e);
            return 0;
        }
    }

}
